﻿using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.Reflection;

namespace zijian666.CommandLine;

/// <summary>
/// 用于标记命令行命令的类
/// </summary>
[AttributeUsage(AttributeTargets.Class, Inherited = true, AllowMultiple = false)]
public class CommandLineActionAttribute : Attribute
{
    /// <summary>
    /// 初始化一个新的 <see cref="CommandLineActionAttribute"/> 实例。
    /// </summary>
    public CommandLineActionAttribute() { }

    /// <summary>
    /// 初始化一个新的 <see cref="CommandLineActionAttribute"/> 实例。
    /// </summary>
    /// <param name="name"></param>
    public CommandLineActionAttribute(string name) => Name = name;

    /// <summary>
    /// 命令的别名
    /// </summary>
    public string[]? Alias { get; set; }

    /// <summary>
    /// 命令的名称
    /// </summary>
    public string? Name { get; set; }

    /// <summary>
    /// 命令的描述
    /// </summary>
    public string? Description { get; set; }

    /// <summary>
    /// 根据类型的特性解析命令的名称、描述和别名
    /// </summary>
    /// <param name="type"></param>
    [MemberNotNull(nameof(Name), nameof(Description), nameof(Alias))]
    internal void Resolve(Type type)
    {
        Name ??= type.GetCustomAttribute<DisplayNameAttribute>()?.DisplayName;
        Description ??= type.GetCustomAttribute<DescriptionAttribute>()?.Description;
        Alias ??= [];
        if (string.IsNullOrWhiteSpace(Name))
        {
            Name = type.Name;
            if (Name.EndsWith("Command", StringComparison.OrdinalIgnoreCase))
            {
                Name = Name[..^"Command".Length];
            }
            else if (Name.EndsWith("CommandLineAction", StringComparison.OrdinalIgnoreCase))
            {
                Name = Name[..^"CommandLineAction".Length];
            }
            else if (Name.EndsWith("Action", StringComparison.OrdinalIgnoreCase))
            {
                Name = Name[..^"Action".Length];
            }
            Name = Name.ToLowerInvariant();
        }
        if (string.IsNullOrWhiteSpace(Description))
        {
            Description = $"Executes the {Name} command.";
        }
    }
}